package com.rad.net.protocol.android;

import android.content.Context;
import android.os.Handler;

import com.rad.net.protocol.android.cache.CacheStrategy;
import com.rad.net.protocol.android.decoder.Decoder;
import com.rad.net.protocol.android.encoder.Encoder;
import com.rad.net.protocol.android.http.HttpTransporter;
import com.rad.net.protocol.android.utils.CfgUtils;
import com.rad.net.protocol.android.utils.LogUtils;
import com.rad.net.protocol.common.cmd.BaseCmd;
import com.rad.net.protocol.common.result.AutoRegisterResult;
import com.rad.net.protocol.common.result.ErrorResult;

/**
 * 该类提供对自动注册，普通联网请求的支持。暂不支持下载文件的操作。 所有使用该网络框架的应用都需要在应用启动时调用
 * {@link NetTask#setup(String, String, String, String)}方法来初始化网络框架 </br></br>
 * 
 * 该类实例只支持单次联网任务，一次联网任务后如需再次联网，请重新获取该类的实例。
 * 
 * @author xinhui.cheng
 * @date 2014-8-27
 * @version 1.0
 */
public class NetTask {

	private static String sAutoRegisterUrl;
	private static boolean sInitialized = false;
	private static Handler sHandler = new Handler();

	private int mTag;
	private NetTaskListener mNetTaskListener;

	private NetController mNetController;
	private Context mContext;
	private boolean mIsUsed = false;

	private NetTask(Context context) {
		mContext = context;
		mNetController = new NetController(context);
	}

	public static NetTask getInstance(Context context) {
//		if (!sInitialized) {
//			throw new IllegalStateException("NetTask not initialized!");
//		}
		NetTask netTask = new NetTask(context);
		return netTask;
	}

	/**
	 * 初始化网络框架
	 * 
	 * @param resultPkg
	 *            返回结果类所在的包名
	 * @param autoRegisterUrl
	 *            自动注册的url地址，不包含需要自动拼接的参数
	 * @param urlHost
	 *            联网的主机地址，不包含需要自动拼接的参数
	 * @param secretKey
	 *            联网加密密钥
	 */
	public static void setup(String resultPkg, String autoRegisterUrl,
			String urlHost, String secretKey) {
		sAutoRegisterUrl = autoRegisterUrl;
		NetController.setDefaultParams(resultPkg, urlHost, secretKey);
		sInitialized = true;
	}

	/**
	 * 设置是否是调试状态，如果设为true则会在控制台打印出日志信息。 正式发布时请设置为false.
	 * 
	 * @param debug
	 */
	public static void setDebug(boolean debug) {
		LogUtils.DEBUG = debug;
	}

	/**
	 * 启动自动注册，该方法是异步的，返回结果通过{@link AutoRegisterListener}返回。
	 * 
	 * @param context
	 * @param tag
	 *            本次任务标识
	 * @param listener
	 */
	public static void startAutoRegisterOnly(Context context,
			AutoRegisterListener listener) {
		if (!sInitialized) {
			throw new IllegalStateException("NetTask not initialized!");
		}
		new Thread(new AutoRegisterRunnable(context, listener)).start();
	}

	/**
	 * 启动网络任务，该方法是异步的，返回结果通过{@link NetTaskListener}返回，该方法会自动调用自动注册，
	 * 只有在自动注册通过或已经自动注册时，才会进行目标任务。 该方法只能调用一次，如需再次使用，请重新获取
	 * {@link NetTask} 的实例。
	 * 
	 * @param cmd
	 *            请求参数对象
	 * @param tag
	 *            本次任务标识
	 * @param listener
	 */
	public void startNetTask(BaseCmd cmd, int tag, NetTaskListener listener) {
		startNetTask(cmd, tag, listener, true);
	}
	
	/**
	 * 启动网络任务，该方法是异步的，返回结果通过{@link NetTaskListener}返回，该方法会不调用自动注册。
	 *  该方法只能调用一次，如需再次使用，请重新获取{@link NetTask} 的实例。
	 * 
	 * @param cmd
	 *            请求参数对象
	 * @param tag
	 *            本次任务标识
	 * @param listener
	 */
	public void startNetTaskNoAutoRegister(BaseCmd cmd, int tag, NetTaskListener listener){
		startNetTask(cmd, tag, listener, false);
	}
	
	private void startNetTask(BaseCmd cmd, int tag, NetTaskListener listener ,boolean isAutoRegister){
		if (mIsUsed) {
			throw new IllegalStateException(
					"startNetTask can be used only once ! please get NetTask instance again!");
		}
		mIsUsed = true;
		mTag = tag;
		mNetTaskListener = listener;
		new Thread(new NetTaskRunnable(cmd , isAutoRegister)).start();
	}
	
	/**
	 * 启动自动注册，该方法是同步的
	 * @param context
	 * @return 如果注册成功则返回结果，失败则返回null;
	 */
	public static AutoRegisterResult startSyncAutoRegisterOnly(Context context){
//		if (!sInitialized) {
//			throw new IllegalStateException("NetTask not initialized!");
//		}
//		AutoRegisterTask task = AutoRegisterTask.getInstance();
//		AutoRegisterResult result = task.doAutoRegister(context,
//				sAutoRegisterUrl);
//		return result;
		return null;
	}
	
	private Object startSyncNetTask(BaseCmd cmd,boolean isAutoRegister){
		//去掉自动注册
//		if(isAutoRegister){
//			// 如果没有自动注册过，则自动注册
//			if (!CfgUtils.hasAutoRegister(mContext)) {
//				AutoRegisterResult result = startSyncAutoRegisterOnly(mContext);
//				// 结果为空则表示自动注册失败
//				if (result == null) {
//					return null;
//				}
//			}
//		}
		Object result = mNetController.startRequest(cmd);
		if (result == null) {
			return new ErrorResult();
		}
		return result;
	}
	
	/**
	 * 启动网络任务，该方法是同步的，该方法会自动调用自动注册，
	 * 只有在自动注册通过或已经自动注册时，才会进行目标任务。
	 * @param cmd 请求对象
	 * @return 如果请求成功则返回正常结果，如果请求失败则返回{@link ErrorResult}
	 */
	public Object startSyncNetTask(BaseCmd cmd){
		return startSyncNetTask(cmd, true);
	}
	
	/**
	 * 启动网络任务，该方法是同步的，该方法不会进行自动注册相关操作，
	 * 
	 * @param cmd 请求对象
	 * @return 如果请求成功则返回正常结果，如果请求失败则返回{@link ErrorResult}
	 */
	public Object startSyncNetTaskNoAutoRegister(BaseCmd cmd){
		return startSyncNetTask(cmd, false);
	}

	/**
	 * 设置联网处理器
	 * 
	 * @param httpTransporter
	 */
	public void setHttpTransporter(HttpTransporter httpTransporter) {
		mNetController.setHttpTransporter(httpTransporter);
	}

	/**
	 * 设置编码器
	 * 
	 * @param encoder
	 */
	public void setEncoder(Encoder encoder) {
		mNetController.setEncoder(encoder);
	}

	/**
	 * 设置解码器
	 * 
	 * @param decoder
	 */
	public void setDecoder(Decoder decoder) {
		mNetController.setDecoder(decoder);
	}
	
	/**
	 * 设置缓存策略
	 * 
	 * @param cacheStrategy
	 */
	public void setCacheStrategy(CacheStrategy cacheStrategy) {
		mNetController.setCacheStrategy(cacheStrategy);
	}

	public interface NetTaskListener {
		void onNetTaskSuccessful(int tag, Object result);
		void onNetTaskError(int tag, ErrorResult error);
	}

	public interface AutoRegisterListener {
		void onAutoRegisterSuccessful(AutoRegisterResult result);
		void onAutoRegisterFailed();
	}

	private class NetTaskRunnable implements Runnable {

		private BaseCmd cmd;
		private boolean isAutoRegister = true;

        public NetTaskRunnable(BaseCmd cmd , boolean isAutoRegister) {
			this.cmd = cmd;
			this.isAutoRegister = isAutoRegister;
		}

		@Override
		public void run() {
			Object result = startSyncNetTask(cmd, isAutoRegister);
			sHandler.post(new NetTaskCallback(result));
		}

	}

	private class NetTaskCallback implements Runnable {

		private Object result;

		public NetTaskCallback(Object result) {
			this.result = result;
		}

		@Override
		public void run() {
			if (mNetTaskListener != null) {
				if (result == null) {
					mNetTaskListener.onNetTaskError(mTag,new ErrorResult());
				} else if(result instanceof ErrorResult){
					mNetTaskListener.onNetTaskError(mTag, (ErrorResult) result);
				} else {
					mNetTaskListener.onNetTaskSuccessful(mTag, result);
				}
			}

		}

	}

	private static class AutoRegisterRunnable implements Runnable {

		private Context context;
		private AutoRegisterListener listener;

		public AutoRegisterRunnable(Context context,
				AutoRegisterListener listener) {
			this.context = context;
			this.listener = listener;
		}

		@Override
		public void run() {
			AutoRegisterResult result = startSyncAutoRegisterOnly(context);
			sHandler.post(new AutoRegisterCallback(result, listener));
		}

	}

	private static class AutoRegisterCallback implements Runnable {

		private AutoRegisterResult result;
		private AutoRegisterListener listener;

		public AutoRegisterCallback(AutoRegisterResult result,
				AutoRegisterListener listener) {
			this.result = result;
			this.listener = listener;
		}

		@Override
		public void run() {
			if (listener != null) {
				if (result == null) {
					listener.onAutoRegisterFailed();
				} else {
					listener.onAutoRegisterSuccessful(result);
				}
			}
		}

	}
	
}
